﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Data;

namespace LSW.Wcf.App
{
    public static class UDataTableExtensions
    {
        private static Dictionary<Type, IList<PropertyInfo>> typeDictionary = new Dictionary<Type, IList<PropertyInfo>>();

        public static IList<PropertyInfo> GetPropertiesForType<T>()
        {
            var type = typeof(T);
            if (!typeDictionary.ContainsKey(typeof(T)))
            {
                typeDictionary.Add(type, type.GetProperties().ToList());
            }
            return typeDictionary[type];
        }

        public static IList<PropertyInfo> GetPropertiesForType(Type Fulltype)
        {
            if (!typeDictionary.ContainsKey(Fulltype))
            {
                typeDictionary.Add(Fulltype, Fulltype.GetProperties().ToList());
            }
            return typeDictionary[Fulltype];
        }

        public static IList<T> ToList<T>(this DataTable table) where T : new()
        {
            IList<PropertyInfo> properties = GetPropertiesForType<T>();
            IList<T> result = new List<T>();

            foreach (var row in table.Rows)
            {
                var item = CreateItemFromRow<T>((DataRow)row, properties, table.Columns);
                result.Add(item);
            }

            return result;
        }

        private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties, DataColumnCollection Cols) where T : new()
        {
            T item = new T();

            foreach (var property in properties)
            {
                if (Cols.Contains(property.Name) && row[property.Name].GetType() != typeof(DBNull))
                {
                    try
                    {
                        property.SetValue(item, row[property.Name], null);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(property.Name + ": " + ex.Message);
                    }
                }
            }

            return item;
        }

        private static object CreateItemFromRow(DataRow row, IList<PropertyInfo> properties, DataColumnCollection Cols, Type fullType)
        {
            object item = Activator.CreateInstance(fullType);

            foreach (var property in properties)
            {
                if (Cols.Contains(property.Name) && row[property.Name].GetType() != typeof(DBNull))
                {
                    try
                    {
                        property.SetValue(item, row[property.Name], null);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(property.Name + ": " + ex.Message);
                    }
                }
            }

            return item;
        }

        public static T ToEntity<T>(this DataTable table) where T : new()
        {
            IList<PropertyInfo> properties = GetPropertiesForType<T>();
            T result = new T();

            if (table.Rows.Count > 0)
            {
                var row = table.Rows[0];
                result = CreateItemFromRow<T>((DataRow)row, properties, table.Columns);
            }
            return result;
        }
    }
}